/*
 * Tencent is pleased to support the open source community by making Tinker available.
 *
 * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
 *
 * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 *
 * https://opensource.org/licenses/BSD-3-Clause
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.evamay.mytinkerdemo.service

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Handler
import android.os.Looper
import android.widget.Toast

import com.evamay.mytinkerdemo.utils.Utils
import com.orhanobut.logger.Logger
import com.tencent.tinker.lib.service.DefaultTinkerResultService
import com.tencent.tinker.lib.service.PatchResult
import com.tencent.tinker.lib.util.TinkerLog
import com.tencent.tinker.lib.util.TinkerServiceInternals
import com.tencent.tinker.loader.shareutil.SharePatchFileUtil

import java.io.File


/**
 * optional, you can just use DefaultTinkerResultService
 * we can restart process when we are at background or screen off
 * 加载补丁后提供Tinker回调
 * 加载热更新插件后，提示成功，锁屏操作后就会加载热更新插件
 */
class SampleResultService : DefaultTinkerResultService() {


    override fun onPatchResult(result: PatchResult?) {
        if (result == null) {
            Logger.e( "SampleResultService received null result!!!!")
            return
        }
        Logger.e(  "SampleResultService receive result: %s", result.toString())

        //first, we want to kill the recover process
        TinkerServiceInternals.killTinkerPatchServiceProcess(applicationContext)

        val handler = Handler(Looper.getMainLooper())
        handler.post {
            if (result.isSuccess) {
                Toast.makeText(applicationContext, "patch success, please restart process", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(applicationContext, "patch fail, please check reason", Toast.LENGTH_LONG).show()
            }
        }
        // is success and newPatch, it is nice to delete the raw file, and restart at once
        // for old patch, you can't delete the patch file
        if (result.isSuccess) {
            val rawFile = File(result.rawPatchFilePath)
            if (rawFile.exists()) {
                Logger.e( "save delete raw patch file")
                SharePatchFileUtil.safeDeleteFile(rawFile)
            }
            //not like TinkerResultService, I want to restart just when I am at background!
            //if you have not install tinker this moment, you can use TinkerApplicationHelper api
            if (checkIfNeedKill(result)) {
                if (Utils.isBackground) {
                    Logger.e(  "it is in background, just restart process")
                    restartProcess()
                } else {
                    //we can wait process at background, such as onAppBackground
                    //or we can restart when the screen off
                    Logger.e(  "tinker wait screen to restart process")
                    ScreenState(applicationContext, object : ScreenState.IOnScreenOff {
                        override fun onScreenOff() {
                            restartProcess()
                        }
                    })
                }
            } else {
                Logger.e(  "I have already install the newly patch version!")
            }
        }
    }

    /**
     * 结束应用进程
     */
    private fun restartProcess() {
        Logger.e( "app is background now, i can kill quietly")
        //you can send service or broadcast intent to restart your process
        android.os.Process.killProcess(android.os.Process.myPid())
    }

    internal class ScreenState(context: Context, onScreenOffInterface: IOnScreenOff?) {
        internal interface IOnScreenOff {
            fun onScreenOff()
        }

        init {
            val filter = IntentFilter()
            filter.addAction(Intent.ACTION_SCREEN_OFF)
            context.registerReceiver(object : BroadcastReceiver() {

                override fun onReceive(context: Context, `in`: Intent?) {
                    val action = if (`in` == null) "" else `in`.action
                    Logger.e(  "ScreenReceiver action [%s] ", action)
                    if (Intent.ACTION_SCREEN_OFF == action) {

                        context.unregisterReceiver(this)

                        onScreenOffInterface?.onScreenOff()
                    }
                }
            }, filter)
        }
    }

    companion object {
        private val TAG = "Tinker.SampleResultService"
    }

}
